# Amazon SimpleDB manager for CLIR
# author: Kai, Brain

import boto
import ConfigParser

sdb = None

def connect_database(config_filename):
    """
    connect to AWS SimpleDB using a configuration file.
    @param config_filename: a configuration filename
    @type config_filename: C{string}
    """
    global sdb
    cfg = ConfigParser.SafeConfigParser()
    cfg.read(config_filename)

    if cfg.has_section('AWS_authentication'):
        sdb = boto.connect_sdb(cfg.get('AWS_authentication', 'public_key'), \
                               cfg.get('AWS_authentication', 'secret_key'))
    else:
        raise Exception('Bad configuration file!')
    
    if cfg.has_section('proxy_settings'):
        try:
            sdb.use_proxy = cfg.getboolean('proxy_settings', 'enable_proxy')
            sdb.protocol = cfg.get('proxy_settings', 'protocol')
            sdb.proxy = cfg.get('proxy_settings', 'proxy')
            sdb.proxy_port = cfg.getint('proxy_settings', 'port')
            sdb.proxy_user = cfg.get('proxy_settings', 'username')
            sdb.proxy_pass = cfg.get('proxy_settings', 'passwd')
        except Exception:
            sdb.use_proxy = False
            print 'Faulty proxy configuration. Proxy disabled.'
    else: sdb.use_proxy = False
    return cfg

def itemize(domain, item_name, aligned_sent, additional_info = {}):
    """
    convert a AlignedSent object into a new simpleDB item.
    item.save() should be handled outside this function.
    @param domain: the domain of the item
    @type domain: C{boto.sdb.domain.Domain}
    @param item_name: the name of this new item
    @type item_name: C{string}
    @param aligned_sent: the AlignedSent object
    @type aligned_sent: C(AlignedSent}
    @param additional_info: a dict of additional info that needed
    @type additional_info: C{dict}
    @return: the AWS SimpleDB item
    @rtype: C{AlignedSent}
    """
    item = domain.new_item(item_name)
    item['ID'] = get_id(domain, item_name)
    item['LANG'] = additional_info['LANG']
    item['SENT'] = ' '.join(aligned_sent.words)
    item['TRANS'] = ' '.join(aligned_sent.mots)
    item['ALIGN'] = aligned_sent.alignment
    item['POSSIBLE_ALIGN'] = aligned_sent.possible_alignment
    item['REV'] = get_revision(additional_info)
    if additional_info.has_key('COPYRIGHT'):
        item['COPYRIGHT'] = additional_info['COPYRIGHT']
 
    return item

def get_id(domain, item_name):
    """
    Get the ID for given item
    @param domain: the domain of the item
    @type domain: C{boto.sdb.domain.Domain}
    @param item_name: the name of the sdb item
    @type item_name: C{string}
    """
    return domain.name + '/' + item_name

def get_revision(additional_info):
    """
    Get revision information for a particular sentence
    @param additional_info: dict containing author and revision information
    @type additional_info: C{dict}
    @return: a string containing revision information
    @rtype: c{string}
    """
    rev = ''
    if additional_info.has_key('REVISION'):
        rev += additional_info['REVISION']
    rev += ' ' + get_date_time()
    if additional_info.has_key('AUTHOR'):
        rev += ' ' + additional_info['AUTHOR']

    return rev

def get_date_time():
    """
    Get current date and time as a string
    @return: current Date and Time
    @rtype: C{string}
    """
    from time import gmtime, strftime
    return strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())

def create_domain_from_corpus(domain_name, aligned_sent_collection, \
                              additional_info = {}):
    """
    bath upload a corpus to a new domain of the online database.
    @param domain_name: the name of this new domain
    @type domain_name: C{string}
    @param aligned_sent_collection: the corpus of AlignedSentCollection
    @type aligned_sent_collection: C{AlignedSentCollection}
    @param additional_info: additional information for attributes
    @type additional_info: C{dict}
    """
    global sdb
    domain = sdb.create_domain(domain_name)
    corpus = aligned_sent_collection.sents
    for i, counter in zip(corpus, xrange(len(corpus))):
        print counter, ': Uploading...',
        item = itemize(domain, repr(counter), i, additional_info)
        item.save()
        print 'Done.'

def from_item_into_alignedsent(item):
    """
    convert an AWS SimpleDB item back into an AlignedSent object.
    @param item: the SimpleDB item
    @type item: C{boto.sdb.item.Item}
    @return: the AlignedSent object
    @rtype: C{boto.sdb.item.Item}
    """
    from aligned_sent import AlignedSent
    aligned_sent = AlignedSent(item['SENT'].split(' '), item['TRANS'].split(' '), item['ALIGN'])
    return aligned_sent

def from_domain_into_corpus(domain):
    """
    convert an AWS SimpleDB domain back into the AlignedSentCollection Object\
    as a corpus.
    @param domain: the SimpleDB domain
    @type domain: C{boto.sdb.domain.Domain}
    @return: the AlignedSentCollection object
    @rtype: C{AlignedSentCollection}
    """
    corpus = AlignedSentCollection()
    for i in domain:
        corpus.add(from_item_into_alignedsent(i))
    return corpus
    
